import werkzeug
from flask import request, make_response, jsonify
from sqlalchemy import func

from apps.model.serializeModel import model_to_list, model_to_dict
from apps.settingApi.switchCase.caseAallFileds import allColumns
from apps.settingApi.switchCase.caseFilter import CASEFILTER
from apps.settingApi.switchCase.caseParameter import caseParameter
from apps.settingApi.switchCase.casePrimaryKey import caseSetPrimaryKey, caseGetPrimaryKey
from apps.settingApi.switchCase.caseRequired import caseRequiredExist
from apps.settingApi.switchCase.caseType import caseColumnsType
from apps.settingApi.switchCase.columnConstructor import hiddenColumn, primaryKeyColumn
from comm.sqlalchemyConfig import db


def getList(modelObj,argsData=None,excludeFiledList=None):
    """
    modelObj 模型
    argsData 参数
    excludeFiledList 隐藏不显示的参数
    """
    filterList = []
    # 获取所有参数get参数
    if argsData == None:
        args = request.args
    else:
        args = argsData
    for itm1 in args:
        # 分割参数用于判断查询类型（等于、大于等于、模糊查询等）
        itmSplit = itm1.split('__', 1)
        filterTpye = ''
        filterFiled = itmSplit[0]
        if len(itmSplit) > 1:
            filterTpye = itmSplit[1]
        if hasattr(modelObj, filterFiled):
            # 获取查询方式
            filter_z = CASEFILTER.get(filterTpye, CASEFILTER['default'])(modelObj, filterFiled, args[itm1])
            filterList.append(filter_z)

    page = args.get('page', None)
    if page == None:
        page = 1
    pageSize = args.get('pageSize', None)
    if pageSize is None:
        pageSize = 10
    pageSize = int(pageSize)
    page = int(page)

    # 获取需要隐藏显示的字段
    if excludeFiledList is None:
        excludeFiledList = hiddenColumn(modelObj)
    objData = {}
    if hasattr(modelObj, "getListData"):
        print('进入自定义查询')
        objData = modelObj.getListData(args, filterList, page, pageSize, excludeFiledList)
    else:
        # 查询数据
        modelDataObj = modelObj.query.filter(*filterList).order_by(modelObj.id.desc()).paginate(page=page, per_page=pageSize, error_out=False)
        result = model_to_list(modelDataObj, excludeFiledList)
        objData["total"] = modelDataObj.total  # 总记录数
        objData["has_next"] = modelDataObj.has_next  # 是否有下一页
        objData["has_prev"] = modelDataObj.has_prev  # 是否有上一页
        objData["page"] = modelDataObj.page  # 当前页
        objData["pages"] = modelDataObj.pages  # 总页数
        objData["pageSize"] = pageSize  # 分页大小
        objData["data"] = result  # 分页大小
    return objData,None
def postList(modelObj,argsData=None):
    """
    modelObj 模型
    argsData 参数
    """
    # 获取所有参数
    if argsData == None:
        if request.is_json == True:
            args = request.get_json()
        else:
            args = request.form
        if len(args) == 0:
            return None,'参数不能为空'
    else:
        args = argsData

    # 获取所有字段
    columnsList = allColumns(modelObj)

    # 校验必填字段是否传递
    _,err = caseRequiredExist(args,columnsList)
    if err != None:
        return None,err

    # 校验数据类型
    _,err = caseColumnsType(args,columnsList)
    if err != None:
        return None,err

    # 判断主键如果是自动曾的话，自动生成数据
    primarDict,err = caseSetPrimaryKey(columnsList)
    if err != None:
        return None,err

    # 拼接数据
    parameterDict = caseParameter(args,columnsList)

    # 当存在主键手动增加时，查询数据并获取排他锁  当当前新增的时候那么其他的人将无法进行新增修改操作
    if len(primarDict) > 0:
        # 获取组件字段
        primarDict_z = {}
        primaryKeyFiled = primaryKeyColumn(modelObj)
        # 设置参数中传递值
        if len(primaryKeyFiled) > 0:
            for itm in primaryKeyFiled:
                if itm in parameterDict.keys():
                    primarDict_z[itm] = parameterDict[itm]
            # 设置自动生成主键中传递值
            for itm in primaryKeyFiled:
                if itm in primarDict.keys():
                    primarDict_z[itm] = primarDict[itm]
        else:
            primarDict_z = primarDict
        result = db.session.query(modelObj).with_for_update().filter_by(**primarDict_z).first()
        # 如果数据不存在，则添加新数据
        if result != None:
            db.session.commit()
            return None,'数据新增失败'
    for itm in primarDict.keys():
        parameterDict[itm] = primarDict[itm]
    try:
        add = modelObj(**parameterDict)
        db.session.add(add)
        db.session.commit()
        db.session.flush()
        hiddenFiled = hiddenColumn(modelObj)
        addData = model_to_dict(add, hiddenFiled)
    except Exception as e:
        if hasattr(e, "data"):
            if type(e.data)==dict:
                msg = e.data.get("msg",None)
                if msg !=None:
                    e = msg
        return None, '新增失败'+repr(e)
    return addData,None
def getPk(modelObj,pk,hiddenFiled=None):
    """
    modelObj 模型
    pk 主键如果是联合组件的话需要拼接
    hiddenFiled 隐藏不显示的参数
    """
    # 判断自定义主键
    primaryKeyFiled = primaryKeyColumn(modelObj)
    # 拼接主键
    primarList = []
    if len(primaryKeyFiled) == 0:
        columnsList = allColumns(modelObj)
        primarList, err = caseGetPrimaryKey(modelObj, columnsList)
        if err != None:
            return None,err
    else:
        for itm in primaryKeyFiled:
            primarList.append(getattr(modelObj, itm))
    if hiddenFiled is None:
        # 获取影藏不需要显示的数据
        hiddenFiled = hiddenColumn(modelObj)
    resultData = {}
    if hasattr(modelObj, "getPkData"):
        resultData, err = modelObj.getPkData(pk, primarList, hiddenFiled)
        if err != None:
            return None,err
    else:
        # 查询数据
        if len(primarList)==1:
            result = modelObj.query.filter(primarList[0] == pk).first()
        else:
            result = modelObj.query.filter(func.concat(*primarList) == pk).first()
        if result == None:
            return None,'没有查询到数据'

        resultData = model_to_dict(result, hiddenFiled)
    return resultData,None
def putPk(modelObj,pk,argsData=None):
    """
    modelObj 模型
    pk 主键如果是联合组件的话需要拼接
    argsData 修改的参数
    """
    if argsData == None:
        if request.is_json == True:
            args = request.get_json()
        else:
            args = request.form
        if len(args) == 0:
            return None,'参数不能为空'
    else:
        args = argsData
    columnsList = allColumns(modelObj)

    # 校验必填字段是否传递
    _, err = caseRequiredExist(args, columnsList,"put")
    if err != None:
        return None,err

    # 校验数据类型
    _, err = caseColumnsType(args, columnsList)
    if err != None:
        return None,err

    # 拼接数据
    parameterDict = caseParameter(args, columnsList)

    # 判断自定义主键
    primaryKeyFiled = primaryKeyColumn(modelObj)
    # 拼接主键
    primarList = []
    if len(primaryKeyFiled) == 0:
        columnsList = allColumns(modelObj)
        primarList, err = caseGetPrimaryKey(modelObj, columnsList)
        if err != None:
            return None,err
    else:
        for itm in primaryKeyFiled:
            primarList.append(getattr(modelObj, itm))
    # 修改删除参数中包含组件的参数
    parameterDictKeys = parameterDict.keys()
    for itm in primarList:
        if itm.name in parameterDictKeys:
            del parameterDict[itm.name]
    # 修改数据
    # db.session.query(modelObj).filter(func.concat(*primarList) == pk).update(parameterDict)
    # db.session.commit()
    try:
        # 查询数据
        if len(primarList) == 1:
            addr = modelObj.query.filter(primarList[0] == pk).with_for_update().first()
        else:
            addr = modelObj.query.filter(func.concat(*primarList) == pk).with_for_update().first()
        for itm in parameterDict.keys():
            setattr(addr, itm, parameterDict[itm])
        db.session.commit()
    except Exception as e:
        if hasattr(e, "data"):
            if type(e.data)==dict:
                msg = e.data.get("msg",None)
                if msg !=None:
                    e = msg
        return None, repr(e)
    # 获取最新数据
    if len(primarList)==1:
        update = modelObj.query.filter(primarList[0] == pk).first()
    else:
        update = modelObj.query.filter(func.concat(*primarList) == pk).first()
    if update is None:
        return None,'获取更新后的数据失败'
    # 获取影藏不需要显示的数据
    hiddenFiled = hiddenColumn(modelObj)
    update = model_to_dict(update, hiddenFiled)
    return update,None
def deletePk(modelObj,pk):
    """
    modelObj 模型
    pk 主键如果是联合组件的话需要拼接
    """
    # 判断自定义主键
    primaryKeyFiled = primaryKeyColumn(modelObj)
    # 拼接主键
    primarList = []
    if len(primaryKeyFiled) == 0:
        columnsList = allColumns(modelObj)
        primarList, err = caseGetPrimaryKey(modelObj, columnsList)
        if err != None:
            return None,err
    else:
        for itm in primaryKeyFiled:
            primarList.append(getattr(modelObj, itm))
    # 查询数据
    if len(primarList)==1:
        result = modelObj.query.filter(primarList[0] == pk).first()
    else:
        result = modelObj.query.filter(func.concat(*primarList) == pk).first()
    if result == None:
        return None,'数据不存在'
    # 获取影藏不需要显示的数据
    hiddenFiled = hiddenColumn(modelObj)
    resultData = model_to_dict(result, hiddenFiled)
    try:
        if len(primarList)==1:
            deletedata = db.session.query(modelObj).filter(primarList[0] == pk).first()
        else:
            deletedata = db.session.query(modelObj).filter(func.concat(*primarList) == pk).first()
        db.session.delete(deletedata)
        db.session.commit()
    except Exception as e:
        return None,'删除失败' + repr(e)
    return resultData,None